﻿//========================================================= 
/**@file PBOC_ReaderDevAdapter.h
 * @brief 设备执行PBOC流程的适配器
 * 
 * @date 2016-11-11   19:16:02
 * @author Zhyioo 
 * @version 1.0
 */ 
//--------------------------------------------------------- 
#ifndef _LIBZHOUYB_PBOC_READERDEVADAPTER_H_
#define _LIBZHOUYB_PBOC_READERDEVADAPTER_H_
//--------------------------------------------------------- 
#include "../../include/Base.h"

#include "../pboc/pboc_app.h"
using namespace zhou_yb::application::pboc;
//--------------------------------------------------------- 
namespace zhou_yb {
namespace application {
namespace device {
//--------------------------------------------------------- 
/// PBOC集成到硬件的指令操作适配器
class PBOC_ReaderDevAdapter :
    public DevAdapterBehavior<IInteractiveTrans>,
    public RefObject
{
public:
    /**
     * @brief 获取卡号
     * @date 2016-11-11 20:31
     * 
     * @param [in] slot 需要操作的卡槽
     * - 卡槽:
     *  - 0x00 接触
     *  - 0xFF 非接
     * .
     * @param [out] cardNumber 获取到的卡号
     */
    bool GetCardNumber(byte slot, ByteBuilder& cardNumber)
    {
        LOG_FUNC_NAME();
        ASSERT_Device();

        ByteBuilder sCmd(8);
        ByteBuilder rCmd(32);
        DevCommand::FromAscii("34 00", sCmd);
        sCmd += slot;

        ASSERT_FuncErrRet(_pDev->Write(sCmd), DeviceError::SendErr);
        ASSERT_FuncErrRet(_pDev->Read(rCmd), DeviceError::RecvErr);

        LOGGER(_log << "卡号:<" << rCmd.GetString() << ">\n");
        cardNumber += rCmd;

        return _logRetValue(true);
    }
    /**
     * @brief 设备中获取IC卡信息
     * @date 2016-11-11 20:45
     * 
     * @param [in] slot 需要操作的卡槽
     * @param [in] gpoToken GPO返回的AFL数据
     * @param [in] tagHex 需要获取的标签(16进制格式)
     * @param [out] appData 获取到的应用数据
     */
    bool GetInformation(byte slot, const GPO_Token& gpoToken, const ByteArray& tagHex, ByteBuilder& appData)
    {
        LOG_FUNC_NAME();
        LOGGER(_log << "Slot:<" << static_cast<int>(slot) << ">\n";
        _log << "TAG:<";_log.WriteStream(tagHex) << ">\n");
        ASSERT_Device();

        ByteBuilder gpo(32);
        TlvConvert::ToHeaderBytes(0x94, gpo);
        TlvConvert::ToLengthBytes(gpoToken.AFL_List.size() * 4, gpo);
        list_t<PBOC_Library::AFL>::const_iterator gpoitr;
        for(gpoitr = gpoToken.AFL_List.begin();gpoitr != gpoToken.AFL_List.end();++gpoitr)
        {
            gpo += (gpoitr->Sfi << 3);
            gpo += gpoitr->Start;
            gpo += gpoitr->End;
            gpo += gpoitr->Len;
        }

        ByteBuilder tagBcd(64);
        ByteBuilder recBuff(64);
        ByteBuilder dataBuff(64);

        TlvElement tagElement = TlvElement::Parse(tagHex, TlvElement::HeaderOnly);
        TlvElement subElement = tagElement.MoveNext();
        while(!subElement.IsEmpty())
        {
            TlvHeader header = subElement.GetHeader();
            if(PBOC_Library::IsGetDataTag(header))
            {
                TlvConvert::ToHeaderBytes(header, dataBuff);
            }
            else
            {
                TlvConvert::ToHeaderBytes(header, recBuff);
            }
            subElement = tagElement.MoveNext();
        }

        ByteBuilder sCmd(32);
        ByteBuilder rCmd(64);

        DevCommand::FromAscii("34 01", sCmd);
        sCmd += slot;
        sCmd += gpo;
        TlvConvert::MakeTLV(0x71, dataBuff, sCmd);
        TlvConvert::MakeTLV(0x72, recBuff, sCmd);

        LOGGER(_log.WriteLine("组装后的标签指令:").WriteStream(sCmd) << endl);

        ASSERT_FuncErrRet(_pDev->Write(sCmd), DeviceError::SendErr);
        ASSERT_FuncErrRet(_pDev->Read(rCmd), DeviceError::RecvErr);

        LOGGER(_log.WriteLine("Info:").WriteLine(rCmd));
        appData += rCmd;

        return _logRetValue(true);
    }
};
//--------------------------------------------------------- 
} // namespace device
} // namespace application
} // namespace zhou_yb
//--------------------------------------------------------- 
#endif // _LIBZHOUYB_PBOC_READERDEVADAPTER_H_
//========================================================= 